package com.nanchen.compresshelper;

import ohos.app.Context;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageFormat;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;
import ohos.utils.net.Uri;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class BitmapUtil {
    private BitmapUtil() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    public static PixelMap getScaledPixelmap(Context context, String imagePath, float maxWidth, float maxHeight, PixelFormat config) {
        PixelMap scaledBitmap = null;
        ImageSource imageSource = ImageSource.create(imagePath, null);
        PixelMap bmp = imageSource.createPixelmap(null);
        Size size = bmp.getImageInfo().size;
        int actualHeight = size.height;
        int actualWidth = size.width;
        float imgRatio = (float) actualWidth / actualHeight;
        float maxRatio = maxWidth / maxHeight;
        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;
            }
        }
        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        decodingOpts.sampleSize = calculateInSampleSize(size, actualWidth, actualHeight);
        decodingOpts.desiredSize = new Size(actualWidth, actualHeight);
        decodingOpts.desiredPixelFormat = config;
        scaledBitmap = imageSource.createPixelmap(decodingOpts);
        return scaledBitmap;
    }

    static File compressImage(
            Context context, String imagePath, float maxWidth, float maxHeight,
            ImageFormat.ComponentType compressFormat, PixelFormat config,
            int quality, String parentPath, String prefix, String fileName) {
        String extension = "jpg";
        String format = "image/jpeg";
        switch (compressFormat) {
            case JPEG:
                extension = "jpg";
                format = "image/jpeg";
                break;
        }
        FileOutputStream out = null;
        String filePath = generateFilePath(context, parentPath, imagePath, extension, prefix, fileName);
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                boolean isCreate = file.createNewFile();
            }
            out = new FileOutputStream(file);
            // 通过文件名写入
            PixelMap newBmp = BitmapUtil.getScaledPixelmap(context, imagePath, maxWidth, maxHeight, config);
            if (newBmp != null) {
                ImagePacker imagePacker = ImagePacker.create();
                ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
                packingOptions.quality = quality;
                packingOptions.format = format;
                imagePacker.initializePacking(out, packingOptions);
                imagePacker.addImage(newBmp);
                imagePacker.finalizePacking();
            }
        } catch (IOException ex) {
            Logger.getLogger(BitmapUtil.class.getName()).log(Level.SEVERE, ex.getMessage());
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ignored) {
                Logger.getLogger(BitmapUtil.class.getName()).log(Level.SEVERE, ignored.getMessage());
            }
        }
        return new File(filePath);
    }

    private static String generateFilePath(
            Context context, String parentPath, Uri uri,
            String extension, String prefix, String fileName) {
        File file = new File(parentPath);
        if (!file.exists()) {
            boolean isMk = file.mkdirs();
        }
        /** if prefix is null, set prefix "" */
        prefix = StringUtil.isEmpty(prefix) ? "" : prefix;
        /** reset fileName by prefix and custom file name */
        fileName = StringUtil.isEmpty(fileName) ? prefix + FileUtil.splitFileName(FileUtil.getFileName(context, uri))[0] : fileName;
        try {
            return file.getCanonicalPath() + File.separator + fileName + "." + extension;
        } catch (IOException ex) {
            Logger.getLogger(BitmapUtil.class.getName()).log(Level.SEVERE, ex.getMessage());
            return null;
        }
    }

    private static String generateFilePath(
            Context context, String parentPath, String uri,
            String extension, String prefix, String fileName) {
        File file = new File(parentPath);
        if (!file.exists()) {
            boolean isMk = file.mkdirs();
        }
        /** if prefix is null, set prefix "" */
        prefix = StringUtil.isEmpty(prefix) ? "" : prefix;
        /** reset fileName by prefix and custom file name */
        fileName = StringUtil.isEmpty(fileName) ? prefix + FileUtil.splitFileName(uri)[0] : fileName;
        try {
            return file.getCanonicalPath() + File.separator + fileName + "." + extension;
        } catch (IOException ex) {
            Logger.getLogger(BitmapUtil.class.getName()).log(Level.SEVERE, ex.getMessage());
            return null;
        }
    }

    static int calculateInSampleSize(Size size, int reqWidth, int reqHeight) {
        int height = size.height;
        int width = size.width;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            int halfHeight = height / 2;
            for (int halfWidth = width / 2; halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth; inSampleSize *= 2) {
            }
        }
        return inSampleSize;
    }

}
